/*
 * Road.cpp
 *
 *  Created on: Oct 25, 2009
 *      Author: jbarreneche
 */

#include "Road.h"
#include "utils/OverlappingMatcher.h"

#include "util/exceptions/ElementNotFoundException.h"

Road::Road(string name, RoadType roadType) {
	this->name = name;
	this->roadType = roadType;
}

Road::~Road() {
	while (!this->roadSegments.isEmpty()) {
		delete this->roadSegments.removeFirst();
	}
}
util::LinkedList<RoadSegment> Road::getSegments() {
	return this->roadSegments;
}

util::LinkedList<RoadSegment> Road::getSegments(int height) {
	util::LinkedList<RoadSegment>::Iterator it = this->roadSegments.iterator();
	util::LinkedList<RoadSegment> list;
	while (it.hasNext()) {
		RoadSegment* road = it.next();
		if (road->contains(height)) {
			list.add(0, road);
		}
	}
	return list;
}
MapPoint Road::getPointAt(int height) throw(UnexistingAddressException){
	util::LinkedList<RoadSegment> list = this->getSegments(height);
	if (list.isEmpty()) {
		throw UnexistingAddressException(this->name, height);
	}
	return MapPoint(list.get(0)->getPointAt(height));
}
RoadSegment* Road::addEdge(Edge* edge, int minHeight, int maxHeight, Intersection *origin, Intersection *destination)
	throw(OverlappingRoadSegmentException) {
	RoadSegment* segment = getSegment(minHeight, maxHeight, origin, destination);
	segment->addEdge(edge, minHeight < maxHeight);
	return segment;
}

RoadSegment* Road::getSegment(int minHeight, int maxHeight, Intersection *origin, Intersection *destination)
	throw(OverlappingRoadSegmentException) {
	OverlappingMatcher matcher(minHeight, maxHeight);
	RoadSegment* segment;
	try {
		segment = this->roadSegments.search(&matcher);
		if (!segment->overlapsExactly(minHeight, maxHeight)) {
			throw OverlappingRoadSegmentException();
		}
	} catch (util::ElementNotFoundException e) {
		segment = new RoadSegment(this, minHeight, maxHeight, origin, destination);
		this->roadSegments.add(0, segment);
	}
	return segment;
}
